package org.eden.heartbeat.core;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eden.heartbeat.api.Constants;
import org.eden.heartbeat.core.configuration.CoreApplicationConfiguration;
import org.eden.heartbeat.api.exception.ConfigurationNotFoundException;
import org.eden.heartbeat.core.exception.PersistenceException;
import org.eden.heartbeat.api.jmx.HeartbeatCore;
import org.eden.heartbeat.api.jmx.HeartbeatCoreMBean;
import org.eden.heartbeat.api.jmx.HeartbeatStatistics;
import org.eden.heartbeat.api.model.MachineInfo;
import org.eden.heartbeat.core.persistence.SimplePersistenceManager;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import java.lang.management.ManagementFactory;

/**
 * This is the main application that starts the monitor and manages its lifecycle.
 *
 * @author trsimoes
 * @version $Revision:$
 */
public class HeartbeatCoreMain {

    private static Log LOG = LogFactory.getLog(HeartbeatCoreMain.class);

    public void execute() {
        try {
            if (LOG.isInfoEnabled()) {
                LOG.info("HeartbeatCoreMain started");
            }

            // load the application configuration
            CoreApplicationConfiguration.loadConfigurations();

            if (LOG.isDebugEnabled()) {
                LOG.debug("Configurations loaded successfully");
            }

            // gets the configured remote machine
            MachineInfo machineInfo = CoreApplicationConfiguration.getConfiguredRemoteMachine();

            MBeanServer server = ManagementFactory.getPlatformMBeanServer();

            // create a new instance of the heartbeat core mbean
            HeartbeatCoreMBean heartbeatCoreMBean = new HeartbeatCore(machineInfo);
            // register it in the MBean server
            server.registerMBean(heartbeatCoreMBean, new ObjectName(Constants.HEARTBEAT_CORE_MBEAN_OBJECT_NAME));
            // automatically start the monitoring thread
            heartbeatCoreMBean.start();

            // create a new instance of the heartbeat statistics mbean
            HeartbeatStatistics heartbeatStatistics = new HeartbeatStatistics();
            // register it in the MBean server
            server.registerMBean(heartbeatStatistics, new ObjectName(Constants.HEARTBEAT_STATISTICS_MBEAN_OBJECT_NAME));

            while (heartbeatCoreMBean.isRunning()) {
                // loop until interrupted
                if (LOG.isTraceEnabled()) {
                    LOG.trace("-- monitor keep alive --");
                }
                try {
                    Thread.sleep(CoreApplicationConfiguration.monitorInterval);
                } catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }
        } catch (ConfigurationNotFoundException e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Mandatory configuration not found: " + e.getConfiguration(), e);
            }
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Error running HeartbeatCore", e);
            }
        } finally {
            try {
                SimplePersistenceManager.getInstance().close();

                if (LOG.isInfoEnabled()) {
                    LOG.info("HeartbeatCoreMain gracefully stopped");
                }
            } catch (PersistenceException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error("Error closing the persistence manager before shutting down the application.", e);
                }
            }
        }
    }

    public static void main(String[] args) {
        HeartbeatCoreMain main = new HeartbeatCoreMain();
        main.execute();
    }
}
